﻿using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestGame {
    /// <summary>
    /// The Screen in-charge of the MenuEntries that let the user str the key 
    /// bindings to whatever is chosen. It modifies the keySettings.settings 
    /// file whenever a different binding is chosen or is reverted to the 
    /// default settings. There are no public Event handlers for this Screen.
    /// The Screen exits when the Back MenuEntry is chosen  or the quit menu 
    /// key is pressed.
    /// </summary>
    class ControlOptionsScreen : MenuScreen {
        #region Fields

        MenuEntry upEntry;
        MenuEntry downEntry;
        MenuEntry leftEntry;
        MenuEntry rightEntry;
        MenuEntry aKeyEntry;
        MenuEntry bKeyEntry;
        MenuEntry cKeyEntry;

        MenuEntry defaultEntry;

        MenuEntry back;

        const int UP = 0;
        const int DOWN = 1;
        const int LEFT = 2;
        const int RIGHT = 3;
        const int A = 4;
        const int B = 5;
        const int C = 6;

        const string CONFIRM_MSG = "Are you sure you want to\nrevert to default settings?";

        #endregion

        #region Initialization

        /// <summary>
        /// Constructors a ControlOptionsScreen that has several 
        /// MenuEntries that control the different key bindings the game uses.
        /// </summary>
        public ControlOptionsScreen() : base("Control Options") {
            upEntry = new MenuEntry("Up");
            downEntry = new MenuEntry("Down");
            leftEntry = new MenuEntry("Left");
            rightEntry = new MenuEntry("Right");
            back = new MenuEntry("Back");
            aKeyEntry = new MenuEntry("A Key");
            bKeyEntry = new MenuEntry("B Key");
            cKeyEntry = new MenuEntry("C Key");
            defaultEntry = new MenuEntry("Restore Defaults");

            // Hook up menu event handlers.
            back.Selected += OnCancel;
            upEntry.Selected += OnOptionChosen;
            downEntry.Selected += OnOptionChosen;
            leftEntry.Selected += OnOptionChosen;
            rightEntry.Selected += OnOptionChosen;
            aKeyEntry.Selected += OnOptionChosen;
            bKeyEntry.Selected += OnOptionChosen;
            cKeyEntry.Selected += OnOptionChosen;
            defaultEntry.Selected += OnDefaultChosen;
            
            // Add entries to the menu.
            MenuEntries.Add(upEntry);
            MenuEntries.Add(downEntry);
            MenuEntries.Add(leftEntry);
            MenuEntries.Add(rightEntry);
            MenuEntries.Add(aKeyEntry);
            MenuEntries.Add(bKeyEntry);
            MenuEntries.Add(cKeyEntry);
            MenuEntries.Add(defaultEntry);
            MenuEntries.Add(back);

            UpdateText();
        }

        /// <summary>
        /// Updates the MenuEntry text for the different key bindings with their current
        /// bindings.
        /// </summary>
        void UpdateText() {
            String upText = String.Format("Up: <{0}>", KeySettings.Default.up);
            String downText = String.Format("Down: <{0}>", KeySettings.Default.down);
            String leftText = String.Format("Left: <{0}>", KeySettings.Default.left);
            String rightText = String.Format("Right: <{0}>", KeySettings.Default.right);
            String aText = String.Format("A Key: <{0}>", KeySettings.Default.a);
            String bText = String.Format("B Key: <{0}>", KeySettings.Default.b);
            String cText = String.Format("C Key: <{0}>", KeySettings.Default.c);

            upEntry.Text = upText;
            downEntry.Text = downText;
            leftEntry.Text = leftText;
            rightEntry.Text = rightText;
            aKeyEntry.Text = aText;
            bKeyEntry.Text = bText;
            cKeyEntry.Text = cText;
        }

        #endregion

        #region Event Handlers

        /// <summary>
        /// The Method called if any of the Key re-binding options are chosen.
        /// All the MenuEntries call to this, and the SelectedEntry determines which 
        /// MenuEntry called it.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void OnOptionChosen(object sender, PlayerIndexEventArgs e) {
            KeyInputScreen screen = new KeyInputScreen();

            screen.Accepted += keyInputSelected;

            ScreenManager.AddScreen(screen, e.PlayerIndex);
        }

        /// <summary>
        /// The Method called once the Default menu entry is chosen.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void OnDefaultChosen(object sender, PlayerIndexEventArgs e) {
            ConfirmMessageBoxScreen screen = new ConfirmMessageBoxScreen(CONFIRM_MSG);

            screen.Accepted += OnDefaultConfirm;

            ScreenManager.AddScreen(screen, e.PlayerIndex);
        }

        /// <summary>
        /// The Method called if the Confirmation dialog is successful.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void OnDefaultConfirm(object sender, PlayerIndexEventArgs e) {
            KeySettings.Default.Reset();
            KeySettings.Default.Save();
            UpdateText();
        }


        /// <summary>
        /// This Method is called upon a successful KeyInputScreen call. It 
        /// passes the first Key pressed. 
        /// </summary>
        /// <param name="sender">The first Keys that is pressed</param>
        /// <param name="e"></param>
        void keyInputSelected(object sender, PlayerIndexEventArgs e) {
            Keys key = (Keys)sender;

            // A safety measure to make sure nothing went wrong
            if (key != Keys.None) {
                switch (SelectedEntry) {
                    case UP:
                        KeySettings.Default.up = key;
                        break;
                    case DOWN:
                        KeySettings.Default.down = key;
                        break;
                    case LEFT:
                        KeySettings.Default.left = key;
                        break;
                    case RIGHT:
                        KeySettings.Default.right = key;
                        break;
                    case A:
                        KeySettings.Default.a = key;
                        break;
                    case B:
                        KeySettings.Default.b = key;
                        break;
                    case C:
                        KeySettings.Default.c = key;
                        break;
                    default:
                        throw new NotImplementedException("Key assignment to unknown binding");
                }
            }

            KeySettings.Default.Save();
            UpdateText();
        }

        #endregion
    }
}
